package la.bbs558.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import la.bbs558.entity.*;
import la.bbs558.entity.vo.IndexCollectVO;
import la.bbs558.entity.vo.IndexPostVO;
import la.bbs558.entity.vo.IndexSectionVO;
import la.bbs558.entity.vo.StatisticsVO;
import la.bbs558.entity.enums.RedisKey;
import la.bbs558.entity.params.BbsPostPage;
import la.bbs558.service.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class StatisticsServiceImpl implements StatisticsService {

    //开启缓存用户数的阈值
    public static final int CACHE_USER_COUNT = 10000;
    //开启缓存发帖数的阈值
    public static final int CACHE_POST_COUNT = 100000;
    @Resource
    private UserService userService;
    @Resource
    private BbsBoardService bbsBoardService;
    @Resource
    private BbsPostService bbsPostService;
    @Resource
    private UserOptionService userOptionService;
    @Resource
    private BbsSectionService bbsSectionService;
    @Resource
    private AdContentService adContentService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private BbsReplyService bbsReplyService;

    @Override
    public StatisticsVO statistics() {
        String key = RedisKey.INDEX_STATISTICS.getKey();
        Object redisObj = redisTemplate.opsForValue().get(key);
        try {
            if (redisObj instanceof StatisticsVO) {
                return (StatisticsVO) redisObj;
            }
        } catch (Exception e) {
            //ignore
        }
        //查询最近一个月的数据
        DateTime now = DateUtil.date();
        DateTime beginOfDay = DateUtil.beginOfDay(now);
        DateTime endOfDay = DateUtil.endOfDay(now);
        DateTime early28Day = DateUtil.offsetDay(now,-28);
        Integer addUserCount = userService.lambdaQuery().between(User::getCreateTime, early28Day, now).count();
        int userCount = userService.count();
        int postCount = bbsPostService.lambdaQuery().eq(BbsPost::getState,1).count();
        int replyCount = bbsReplyService.lambdaQuery().eq(BbsReply::getState, 1).count();
        Integer todayPostCnt = bbsPostService.lambdaQuery().between(BbsPost::getCreateTime, beginOfDay, endOfDay).count();
        Integer todayReplyCnt = bbsReplyService.lambdaQuery().between(BbsReply::getCreateTime, beginOfDay, endOfDay).count();
        StatisticsVO statisticsVO = new StatisticsVO()
                .setAddUserCount(addUserCount)
                .setUserCount(userCount)
                .setPostCount(postCount)
                .setReplyCount(replyCount)
                .setTodayPostCount(todayPostCnt)
                .setTodayReplyCount(todayReplyCnt)
                ;
        if(userCount > CACHE_USER_COUNT || postCount > CACHE_POST_COUNT){
            //30分钟缓存
            redisTemplate.opsForValue().set(key, statisticsVO, 1, TimeUnit.MINUTES);
        }
        return statisticsVO;
    }

    @Override
    public List<IndexCollectVO> collectBoardList() {
        if (StpUtil.getLoginId() == null) {
            return Collections.emptyList();
        }
        long userId = StpUtil.getLoginIdAsLong();
        return userOptionService.collectBoardList(userId);
    }

    @Override
    public IndexPostVO post() {
        List<BbsPost> hots = bbsPostService.hots();
        List<BbsPost> news = bbsPostService.news();
        List<BbsPost> highLights = bbsPostService.highLights();
        List<BbsPost> tools = bbsPostService.tools();
        return IndexPostVO.builder()
                .highLights(highLights)
                .tools(tools)
                .hots(hots)
                .news(news)
                .build();
    }

    @Override
    public List<IndexSectionVO> section() {
        List<BbsSection> list = bbsSectionService.lambdaQuery().orderByDesc(BbsSection::getSort).list();
        List<IndexSectionVO> res = new ArrayList<>();
        //List<AdContent> adsByPosition = adContentService.getAdsByPosition(AdPosition.LAYOUT_FILL.getCode(), null);
        for (BbsSection bbsSection : list) {
            List<BbsBoard> bbsBoards = bbsBoardService.lambdaQuery().eq(BbsBoard::getSectionId, bbsSection.getId()).orderByDesc(BbsBoard::getCreateTime).list();
            IndexSectionVO sectionVO = new IndexSectionVO()
                    .setSectionName(bbsSection.getSectionName())
                    .setCreateUser(bbsSection.getCreateUser())
                    .setUpdateTime(bbsSection.getUpdateTime())
                    .setSectionId(bbsSection.getId())
                    .setBoards(bbsBoards);
            res.add(sectionVO);
            //TODO 查询出来的版块数量不是3的倍数，需要使用广告补齐
        }
        return res;
    }
}
